package com.nsyue.auth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nsyue.auth.constant.SysConstant;
import com.nsyue.auth.controller.result.ApiStatusEnum;
import com.nsyue.auth.dao.UserDao;
import com.nsyue.auth.domain.granter.PlatformAuthenticationToken;
import com.nsyue.auth.dto.SyncLoginDTO;
import com.nsyue.auth.dto.SyncRegisterDTO;
import com.nsyue.auth.entity.*;
import com.nsyue.auth.exception.NsyueAuthException;
import com.nsyue.auth.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户表(User)表服务实现类
 *
 * @author laixm
 * @since 2023-05-06 15:18:01
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private ThirdSystemService thirdSystemService;

    @Autowired
    private UserSystemService userSystemService;

    @Override
    public PlatformAuthenticationToken loadPlatformAuthenticationByPhone(String appid, String phone) {
        User user = getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
        if (ObjectUtil.isEmpty(user)) {
            throw new NsyueAuthException(ApiStatusEnum.USER_CODE_ERROR);
        }
        // 查询用户是否此系统的
        ThirdSystem thirdSystem = thirdSystemService.getOne(new LambdaQueryWrapper<ThirdSystem>().eq(ThirdSystem::getAppid, appid));
        long sysCun = 0;
        if (thirdSystem != null) {
            sysCun = userSystemService.count(new LambdaQueryWrapper<UserSystem>().eq(UserSystem::getUserId, user.getId()).eq(UserSystem::getSysId, thirdSystem.getId()));
        }
        if (sysCun < 1) {
            throw new NsyueAuthException(ApiStatusEnum.NOT_REGISTERED);
        }
        //获取用户权限
        List<UserRole> userRoleList = userRoleService.list(new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, user.getId()));
        if (ObjectUtil.isEmpty(userRoleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<Long> roleIdList = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        List<Role> roleList = roleService.list(new QueryWrapper<Role>().lambda()
                .in(Role::getId,roleIdList).eq(Role::getStatus, SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(roleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().lambda()
                .in(RolePermission::getRoleId,roleIdList));
        if (ObjectUtil.isEmpty(rolePermissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }
        List<Long> permissionIdList = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
        List<Permission> permissionList = permissionService.list(new QueryWrapper<Permission>().lambda()
                .in(Permission::getId,permissionIdList).eq(Permission::getStatus,SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(permissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }

        String roleStr = roleList.stream().distinct().map(Role::getRoleCode).collect(Collectors.joining(","));
        String permissionStr = permissionList.stream().distinct().map(Permission::getPermissionCode).collect(Collectors.joining(","));
        String authStr = roleStr + SysConstant.SEPARATOR + permissionStr;
        // 这里设置权限和角色
        List<GrantedAuthority> grantedAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(authStr);

        return new PlatformAuthenticationToken(user.getUsername(), grantedAuthorities);
    }

    @Override
    public OAuth2Authentication loadPrincipal(SyncLoginDTO syncLoginDTO, Map<String, String> parameters) {
        User user = getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, syncLoginDTO.getMobile()));
        if (ObjectUtil.isEmpty(user)) {
            throw new NsyueAuthException(ApiStatusEnum.USER_CODE_ERROR);
        }
        parameters.put(SysConstant.USERNAME, user.getUsername());
        parameters.put(SysConstant.PASSWORD, SecureUtil.md5(user.getUsername() + SysConstant.FREE_PASSWORD + user.getPhone()));
        // 查询用户是否此系统的
        ThirdSystem thirdSystem = thirdSystemService.getOne(new LambdaQueryWrapper<ThirdSystem>().eq(ThirdSystem::getAppid, syncLoginDTO.getAppid()));
        long sysCun = 0;
        if (thirdSystem != null) {
            sysCun = userSystemService.count(new LambdaQueryWrapper<UserSystem>().eq(UserSystem::getUserId, user.getId()).eq(UserSystem::getSysId, thirdSystem.getId()));
        }
        if (sysCun < 1) {
            throw new NsyueAuthException(ApiStatusEnum.NOT_REGISTERED);
        }
        //获取用户权限
        List<UserRole> userRoleList = userRoleService.list(new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, user.getId()));
        if (ObjectUtil.isEmpty(userRoleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<Long> roleIdList = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        List<Role> roleList = roleService.list(new QueryWrapper<Role>().lambda()
                .in(Role::getId,roleIdList).eq(Role::getStatus, SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(roleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().lambda()
                .in(RolePermission::getRoleId,roleIdList));
        if (ObjectUtil.isEmpty(rolePermissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }
        List<Long> permissionIdList = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
        List<Permission> permissionList = permissionService.list(new QueryWrapper<Permission>().lambda()
                .in(Permission::getId,permissionIdList).eq(Permission::getStatus,SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(permissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }

        String roleStr = roleList.stream().distinct().map(Role::getRoleCode).collect(Collectors.joining(","));
        String permissionStr = permissionList.stream().distinct().map(Permission::getPermissionCode).collect(Collectors.joining(","));
        String authStr = roleStr + SysConstant.SEPARATOR + permissionStr;
        // 这里设置权限和角色
        List<GrantedAuthority> grantedAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(authStr);
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(syncLoginDTO.getAppid());

        OAuth2Request oAuth2Request = new OAuth2Request(parameters,
                syncLoginDTO.getAppid(),
                grantedAuthorities,
                true,
                clientDetails.getScope(),
                clientDetails.getResourceIds(),
                null,
                null
                , null
        );
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUsername(), parameters.get(SysConstant.PASSWORD), grantedAuthorities);
        return new OAuth2Authentication(oAuth2Request, authenticationToken);
    }

    @Override
    public String registerBatch(List<SyncRegisterDTO> registerDTOList) {
        String register_code = RandomUtil.randomString(RandomUtil.BASE_CHAR_NUMBER, 5) + "-" + System.currentTimeMillis();
        // todo 暂时不用写
        return register_code;
    }

    @Override
    public UserDetails loadUserByPlatformId(String platformId) {
        User user = getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, platformId));
        if (user == null){
            throw new NsyueAuthException(ApiStatusEnum.USER_CODE_ERROR);
        }
        //获取用户权限
        List<UserRole> userRoleList = userRoleService.list(new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId,user.getId()));
        if (ObjectUtil.isEmpty(userRoleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<Long> roleIdList = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        List<Role> roleList = roleService.list(new QueryWrapper<Role>().lambda()
                .in(Role::getId,roleIdList).eq(Role::getStatus, SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(roleList)){
            throw new NsyueAuthException(ApiStatusEnum.NO_ROLE);
        }
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().lambda()
                .in(RolePermission::getRoleId,roleIdList));
        if (ObjectUtil.isEmpty(rolePermissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }
        List<Long> permissionIdList = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
        List<Permission> permissionList = permissionService.list(new QueryWrapper<Permission>().lambda()
                .in(Permission::getId,permissionIdList).eq(Permission::getStatus,SysConstant.STR_Z_ONE));
        if (ObjectUtil.isEmpty(permissionList)){
            throw new NsyueAuthException(ApiStatusEnum.UNAUTHORIZED);
        }

        String collect = permissionList.stream().map(Permission::getPermissionCode).collect(Collectors.joining(","));
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(collect));
    }
}

